package com.github.cuter44.wxmsg.servlet;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;

import java.util.Properties;
import static com.github.cuter44.wxpay.util.XMLParser.parseXML;
import static com.github.cuter44.wxmsg.msg.MsgParser.parseMsg;

import com.github.cuter44.wxmsg.WxmsgDispatcher;
import com.github.cuter44.wxmsg.WxmsgHandler;
import com.github.cuter44.wxmsg.msg.*;
import com.github.cuter44.wxmsg.reply.*;
import com.github.cuter44.wxmsg.constants.*;

public class WxmsgGatewayServlet extends HttpServlet
{
    
    private static final long serialVersionUID = 6414935366203288623L;

    private static Logger logger = Logger.getLogger(WxmsgGatewayServlet.class);
    
    
    public static final String KEY_SIGNATURE    = "signature";
    public static final String KEY_TIMESTAMP    = "timestamp";
    public static final String KEY_NONCE        = "nonce";
    public static final String KEY_ECHOSTR      = "echostr";

    protected WxmsgDispatcher dispatcher;

    @Override
    public void init(ServletConfig config)
    {
        this.dispatcher = WxmsgDispatcher.getDefaultInstance();

        if (Boolean.valueOf(config.getInitParameter("com.github.cuter44.wxmsg.msggateway.dump")))
        {
            this.dispatcher.subscribe(
                MsgType.POSTPROCESS,
                new WxmsgHandler()
                {
                    @Override
                    public boolean handle(WxmsgBase msg)
                    {
                        logger.debug(" * WxmsgGateway dump");
                        logger.debug(msg.getProperties());

                        return(false);
                    }
                }
            );
        }

        if (Boolean.valueOf(config.getInitParameter("com.github.cuter44.wxmsg.msggateway.acceptalllinkin")))
        {
            this.dispatcher.subscribe(
                MsgType.ECHO,
                new WxmsgHandler()
                {
                    @Override
                    public boolean handle(WxmsgBase msg)
                    {
                        return(true);
                    }
                }
            );
        }

        if (Boolean.valueOf(config.getInitParameter("com.github.cuter44.wxmsg.msggateway.echotext")))
        {
            this.dispatcher.subscribe(
                MsgType.text,
                new WxmsgHandler()
                {
                    @Override
                    public boolean handle(WxmsgBase msg)
                    {
                        MsgText m = (MsgText)msg;
                        m.setReply(new ReplyText(m).setContent(m.getContent()));

                        return true;
                    }
                }
            );
        }

    }

    public void onError(Exception ex, HttpServletRequest req, HttpServletResponse resp)
        throws ServletException
    {
        ex.printStackTrace();
    }

    /** Echo
     */
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws IOException, ServletException
    {
        try
        {
            req.setCharacterEncoding("utf-8");
            resp.setCharacterEncoding("utf-8");
            resp.setContentType("text/plain; charset=utf-8");

            
            logger.debug(KEY_SIGNATURE + " : " + req.getParameter(KEY_SIGNATURE));
            logger.debug(KEY_TIMESTAMP + " : " + req.getParameter(KEY_TIMESTAMP));
            logger.debug(KEY_NONCE + " : " + req.getParameter(KEY_NONCE));
            logger.debug(KEY_ECHOSTR + " : " + req.getParameter(KEY_ECHOSTR));
            
            Properties p = new Properties();

            p.setProperty(KEY_SIGNATURE , req.getParameter(KEY_SIGNATURE)   );
            p.setProperty(KEY_TIMESTAMP , req.getParameter(KEY_TIMESTAMP)   );
            p.setProperty(KEY_NONCE     , req.getParameter(KEY_NONCE)       );
            p.setProperty(KEY_ECHOSTR   , req.getParameter(KEY_ECHOSTR)     );

            Echo e = new Echo(p);

            if (this.dispatcher.handleEcho(e)){
                
                logger.debug("resp.getWriter.write");
                
                resp.getWriter().write(e.getProperty(KEY_ECHOSTR));
            }

            return;
        }
        catch (Exception ex)
        {
            this.onError(ex, req, resp);
        }
    }

    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws IOException, ServletException
    {
        try
        {
            req.setCharacterEncoding("utf-8");
            InputStream reqBody = req.getInputStream();

            String text = IOUtils.toString(reqBody);
            logger.debug(text);
            
            resp.setCharacterEncoding("utf-8");
            PrintWriter out = resp.getWriter();

            Properties parsedProp = parseXML(text);
            WxmsgBase msg = parseMsg(parsedProp);

            if (dispatcher.dispatcher(msg))
            {
                resp.setContentType("text/xml; charset=utf-8");
                String content = msg.getReply().build().toContent();
                logger.debug(content);
                out.print(content);
            }
            else
            {
                resp.setContentType("text/plain; charset=utf-8");
                out.print("success");
            }
        }
        catch (Exception ex)
        {
            this.onError(ex, req, resp);
        }

        return;
    }
}
